package cn.com.dhcc.turbo.service.queue.tlq;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import cn.com.dhcc.app.core.dao.CrudDao;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.service.AbstractCrudService;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.service.Log.LOGTYPE;
import cn.com.dhcc.app.core.util.BeanMapper;
import cn.com.dhcc.app.core.util.JsonUtil;
import cn.com.dhcc.app.core.util.Status;
import cn.com.dhcc.app.core.util.UUIDGenerator;
import cn.com.dhcc.app.pub.core.consts.AppConst;
import cn.com.dhcc.app.pub.core.consts.AppIocBean;
import cn.com.dhcc.app.pub.core.consts.TlqConfig;
import cn.com.dhcc.turbo.dao.registry.NodePipelineDao;
import cn.com.dhcc.turbo.dao.registry.PipelineRegionDao;
import cn.com.dhcc.turbo.dao.registry.QueueDao;
import cn.com.dhcc.turbo.entity.exch.QueueFileMsgWrapper;
import cn.com.dhcc.turbo.entity.registry.NodeInfo;
import cn.com.dhcc.turbo.entity.registry.NodePipeline;
import cn.com.dhcc.turbo.entity.registry.Queue;
import cn.com.dhcc.turbo.entity.registry.tlq.TlqLq;
import cn.com.dhcc.turbo.entity.registry.tlq.TlqSq;
import cn.com.dhcc.turbo.service.queue.QueueService;
import cn.com.dhcc.turbo.service.registry.BaseInfoService;
import cn.com.dhcc.turbo.service.registry.vo.PipeLineTlq;

@Service(AppIocBean.TLQ_QUEUE_SERVICE_BEAN)
public class TlqQueueService extends AbstractCrudService<Queue> implements QueueService {
	private static Logger logger = Log.getLogger(LOGTYPE.TLQ);
	@Autowired
	private QueueDao queueDao;
	
	@Autowired
	private PipelineRegionDao pipelineRegionDao;
	
	
	@Autowired
	private NodePipelineDao nodePipelineDao;
	@Autowired
	private TlqOptService tlqOptService;
	@Autowired
	@Qualifier(AppIocBean.BASE_INFO_SERVICEIMPL_BEAN)
	private BaseInfoService baseInfoService;
	
	@Override
	public CrudDao<Queue> getCrudDao() {
		return queueDao;
	}
	public Status sendFile(String queueName,final  QueueFileMsgWrapper  fileMsgWrapper) {
		return tlqOptService.sendFile(queueName, fileMsgWrapper);
	}
	@Override
	public Status sendMessage(String queueName, final Object content) {
		return tlqOptService.sendMessage(queueName, content);
	}

	/**
	 * 判断某个队列是否受某个tlq管控
	 * @return
	 */
	private boolean isMananged(String queue,String ip){
		return pipelineRegionDao.getManagedIP(queue).equals(ip);
	}
	@Override
	public Status addSendQueue(Queue queue) {
		Status status = Status.getInstance();
		String msg = "";
		try {
			status = tlqOptService.addSendQueue(queue);
			if (status.isSuccess()) {
				//数据入库
				int i = queueDao.insert(queue);
				if (i == 1) {
					msg = "新增TLQ发送队列和队列记录成功";
					status.setSuccess(true);
					status.setMsg(msg);
				} else {
					msg = "新增TLQ发送队列成功，但添加相关的队列记录失败";
					status.setSuccess(false);
					status.setMsg(msg);
				}
			}
		} catch (Exception e) {
			msg = "新增发送队列失败:" + e.fillInStackTrace();
			logger.error(msg);
			status.setSuccess(false);
			status.setMsg(msg);
		}
		return status;
	}

	@Override
	public Status addRecvQueue(Queue queue) {
		Status status = Status.getInstance();
		String msg = "";
		try {
			status = tlqOptService.addRecvQueue(queue);
			if (status.isSuccess()) {
				//数据入库
				int i = queueDao.insert(queue);
				if (i == 1) {
					msg = "新增TLQ接收队列和队列记录成功";
					status.setSuccess(true);
					status.setMsg(msg);
				} else {
					msg = "新增TLQ接收队列成功，但添加相关的队列记录失败";
					status.setSuccess(false);
					status.setMsg(msg);
				}
			}
		} catch (Exception e) {
			msg = "新增接收队列失败:" + e.fillInStackTrace();
			logger.error(msg);
			status.setSuccess(false);
			status.setMsg(msg);
		}
		return status;
	}
	/**
	 * 获取发送队列
	 * @return
	 * @throws DaoException
	 */
	public List<Queue> getDbSendQueueList() throws ServiceException {
		try {
			return queueDao.getSendQueueList();
		} catch (DaoException e) {
			throw new ServiceException("获取数据库中的队列列表");
		}
	}
	
	/**
	 * 逻辑：
	 * 队列以数据库记录为准，且当数据库记录中的队列在TLQ中存在时，将这个队列isQueueExist标注为1
	 */
	@Override
	public List<TlqSq> getSendQueueList() {
		Status status = Status.getInstance();
		String msg = "";
		List<TlqSq> sqList = new ArrayList<TlqSq>();
		try {
			List<TlqSq> queueList = tlqOptService.getSqList();
			Map<String, TlqSq> queueMap = new HashMap<String, TlqSq>();
			for (TlqSq queue : queueList) {
				queueMap.put(queue.getQueueName(), queue);
			}
			List<Queue> dbQueueList = queueDao.getSendQueueList();
			List<String> nodeIdList = queueDao.getHasExchNodeIds();
			for (Queue queue : dbQueueList) {
				String[] queNames = queue.getQueueName().split("_");
				if (null == queNames || queNames.length < 4){
					logger.error("数据库中存放队列有误，请检查！");
					continue;
				}
				for (String nodeId : nodeIdList){
					//如果未建立交换关系或交换关系被删除，则无需去查看其tlq队列状态
					if (!queNames[3].equals(nodeId)){
						continue;
					}
					TlqSq tlq = queueMap.get(queue.getQueueName());
					if (tlq != null) {
						tlq.setIsQueueExist(AppConst.YES);
					} else {
						tlq = new TlqSq();
						BeanMapper.copy(queue, tlq);
						tlq.setIsQueueExist(AppConst.NO);
					}
					tlq.setQueueDesc(queue.getQueueDesc());
					tlq.setDestQueueName(queue.getDestQueueName());
					tlq.setDestIp(queue.getDestIp());
					sqList.add(tlq);
				}
			}
		} catch (Exception e) {
			msg = "获取发送队列出现异常:" + e.fillInStackTrace();
			logger.error(msg);
			status.setSuccess(false);
			status.setMsg(msg);
		}
		return sqList;
	}

	
	/**
	 * 逻辑：
	 * 队列以数据库记录为准，且当数据库记录中的队列在TLQ中存在时，将这个队列isQueueExist标注为1
	 */
	@Override
	public List<TlqSq> getSendQueueList(String ip) {
		Status status = Status.getInstance();
		String msg = "";
		List<TlqSq> sqList = new ArrayList<TlqSq>();
		try {
			List<TlqSq> queueList = tlqOptService.getSqList(ip);
			Map<String, TlqSq> queueMap = new HashMap<String, TlqSq>();
			for (TlqSq queue : queueList) {
				queueMap.put(queue.getQueueName(), queue);
			}
			List<Queue> dbQueueList = queueDao.getSendQueueList();
			List<String> nodeIdList = queueDao.getHasExchNodeIds();
			for (Queue queue : dbQueueList) {
				String[] queNames = queue.getQueueName().split("_");
				if (null == queNames || queNames.length < 4){
					logger.error("数据库中存放队列有误，请检查！");
					continue;
				}
				for (String nodeId : nodeIdList){
					//如果未建立交换关系或交换关系被删除，则无需去查看其tlq队列状态
					if (!queNames[3].equals(nodeId)){
						continue;
					}
					if (!isMananged(queue.getQueueName(), ip)) {//判断队列是否属于该ip,如果不属于忽略该队列
						continue;
					}
					
					TlqSq tlq = queueMap.get(queue.getQueueName());
					if (tlq != null) {
						tlq.setIsQueueExist(AppConst.YES);
					} else {
						tlq = new TlqSq();
						BeanMapper.copy(queue, tlq);
						tlq.setIsQueueExist(AppConst.NO);
					}
					/*
					 * Begin
					 * Modify by heweiqiang 
					 * 2016-03-30
					 * 增加“目的节点”项
					 * **/
					String queueDesc = queue.getQueueDesc();
					if (!StringUtils.isEmpty(queueDesc)){
						tlq.setToQueName(queueDesc.substring(queueDesc.lastIndexOf("[") + 1, queueDesc.lastIndexOf("]")));
					} else {
						tlq.setToQueName("-");
					}
					/*
					 * End
					 * **/
					tlq.setQueueDesc(queueDesc);
					tlq.setDestQueueName(queue.getDestQueueName());
					tlq.setDestIp(queue.getDestIp());
					sqList.add(tlq);
				}
			}
		} catch (Exception e) {
			msg = "获取发送队列出现异常:" + e.fillInStackTrace();
			logger.error(msg);
			status.setSuccess(false);
			status.setMsg(msg);
		}
		return sqList;
	}
	
	@Override
	public List<TlqLq> getRecvQueueList() {
		Status status = Status.getInstance();
		String msg = "";
		List<TlqLq> lqList = new ArrayList<TlqLq>();
		try {
			List<TlqLq> queueList = tlqOptService.getLqList();
			Map<String, TlqLq> queueMap = new HashMap<String, TlqLq>();
			for (TlqLq queue : queueList) {
				queueMap.put(queue.getQueueName(), queue);
			}
			List<Queue> dbQueueList = queueDao.getLocalQueueList();
//			List<String> nodeIdList = queueDao.getHasExchNodeIds();
			for (Queue queue : dbQueueList) {
//				for (String nodeId : nodeIdList){
//					if (!queue.getQueueName().contains(nodeId)){
//						continue;
//					}
					TlqLq tlq = queueMap.get(queue.getQueueName());
					if (tlq != null) {
						tlq.setIsQueueExist(AppConst.YES);
					} else {
						tlq = new TlqLq();
						BeanMapper.copy(queue, tlq);
						tlq.setIsQueueExist(AppConst.NO);
					}
					tlq.setQueueDesc(queue.getQueueDesc());
					lqList.add(tlq);
//				}
			}
		} catch (Exception e) {
			msg = "获取本地队列出现异常:" + e.fillInStackTrace();
			logger.error(msg);
			status.setSuccess(false);
			status.setMsg(msg);
		}
		return lqList;
	}

	
	@Override
	public List<TlqLq> getRecvQueueList(String ip) {
		Status status = Status.getInstance();
		String msg = "";
		List<TlqLq> lqList = new ArrayList<TlqLq>();
		try {
			List<TlqLq> queueList = tlqOptService.getLqList(ip);
			Map<String, TlqLq> queueMap = new HashMap<String, TlqLq>();
			for (TlqLq queue : queueList) {
				queueMap.put(queue.getQueueName(), queue);
			}
			List<Queue> dbQueueList = queueDao.getLocalQueueList();
//			List<String> nodeIdList = queueDao.getHasExchNodeIds();
			for (Queue queue : dbQueueList) {
//				for (String nodeId : nodeIdList){
//					if (!queue.getQueueName().contains(nodeId) && !queue.getQueueName().contains("LQ_")){
//						continue;
//					}
					TlqLq tlq = queueMap.get(queue.getQueueName());
					if (tlq != null) {
						tlq.setIsQueueExist(AppConst.YES);
					} else {
						tlq = new TlqLq();
						BeanMapper.copy(queue, tlq);
						tlq.setIsQueueExist(AppConst.NO);
					}
					tlq.setQueueDesc(queue.getQueueDesc());
					lqList.add(tlq);
//				}
			}
		} catch (Exception e) {
			msg = "获取本地队列出现异常:" + e.fillInStackTrace();
			logger.error(msg);
			status.setSuccess(false);
			status.setMsg(msg);
		}
		return lqList;
	}

	@Override
	public boolean isExistQueue(String queueName) {
		String msg = "";
		boolean flag = false;
		try {
			Queue q = queueDao.getByUniqueProperty("queue_name", queueName);
			if (q != null) {
				flag = true;
			}
		} catch (Exception e) {
			msg = "判断本地队列是否存在出现异常:" + e.fillInStackTrace();
			logger.error(msg);
		}
		return flag;
	}
	
	/**
	 * 根据队列名称获取队列对象
	 * @param queueName
	 * @return
	 */
	public Queue getByQueueName(String queueName) {
		String msg = "";
		Queue queue = null;
		try {
			queue = queueDao.getByUniqueProperty("queue_name", queueName);
		} catch (Exception e) {
			msg = "根据队列名称获取队列对象出现异常:" + e.fillInStackTrace();
			logger.error(msg);
		}
		return queue;
	}
	
	/**
	 * 根据队列名称删除队列(仅仅删除数据库记录)
	 * @param queueName
	 * @return
	 */
	public int deleteByQueueName(String queueName) {
		String msg = "";
		Queue queue = null;
		int suc = 0;
		try {
			queue = getByQueueName(queueName);
			if (queue != null) {
				suc = queueDao.delete(queue);
			}
		} catch (Exception e) {
			msg = "根据队列名称删除对象出现异常:" + e.fillInStackTrace();
			logger.error(msg);
		}
		return suc;
	}

	
	@Override
	public Status initSendQueue(NodeInfo to) {
		Status status = Status.getInstance();
		String msg = "";
		try {
			List<Queue> sqList = new ArrayList<Queue>();
			NodeInfo nodeInfo = baseInfoService.getCurrentNodeInfo();
			Date now = new Date();
			NodePipeline nodePipeline = nodePipelineDao.getTlqPipline(to.getId());
			PipeLineTlq pipeLineTlq = JsonUtil.toObject(nodePipeline.getParamStr(),PipeLineTlq.class);
			String destIp = pipeLineTlq.getBrokerIp();
			
			String cmDataQueueName = "SQ_" + nodeInfo.getNodeCode() + "_TO_" + to.getNodeCode() +"_CM_DATA";
			Queue sqCmData = queueDao.getByQueueName(cmDataQueueName);
			if (sqCmData == null) {
				sqCmData = new Queue();
				String cmDataQueueDesc = "从 [" + nodeInfo.getNodeName() + "] 发送到 [" + to.getNodeName() + "] 的发送队列";
				sqCmData.setId(UUIDGenerator.getUUID());
				sqCmData.setNodeId(nodeInfo.getId());
				sqCmData.setQueueType(Queue.QueueType.SQ.value());
				sqCmData.setQueueName(cmDataQueueName);
				sqCmData.setQueueDesc(cmDataQueueDesc);
				sqCmData.setDestIp(destIp);
				sqCmData.setDestQueueName(TlqConfig.LQ_CM_DATA);
				sqCmData.setBrokerType(Queue.BrokerType.TLQ.value());
				sqCmData.setRemark("系统自动创建的发送队列");
				sqCmData.setMtime(now);
				
				sqList.add(sqCmData);
			}
			
			
			
			String sqCmDataMonitorQueueName = "SQ_" + nodeInfo.getNodeCode() + "_TO_" + to.getNodeCode() +"_CM_DATA_LOG";
			Queue sqCmDataMonitor = queueDao.getByQueueName(sqCmDataMonitorQueueName);
			if (sqCmDataMonitor == null) {
				sqCmDataMonitor = new Queue();
				String sqCmDataMonitorQueueDesc = "从 [" + nodeInfo.getNodeName() + "] 发送到 [" + to.getNodeName() + "] 的监控队列";
				sqCmDataMonitor.setId(UUIDGenerator.getUUID());
				sqCmDataMonitor.setNodeId(nodeInfo.getId());
				sqCmDataMonitor.setQueueType(Queue.QueueType.SQ.value());
				sqCmDataMonitor.setQueueName(sqCmDataMonitorQueueName);
				sqCmDataMonitor.setQueueDesc(sqCmDataMonitorQueueDesc);
				sqCmDataMonitor.setDestIp(destIp);
				sqCmDataMonitor.setDestQueueName(TlqConfig.LQ_CM_DATA_LOG);
				sqCmDataMonitor.setBrokerType(Queue.BrokerType.TLQ.value());
				sqCmDataMonitor.setRemark("系统自动创建的发送队列");
				sqCmDataMonitor.setMtime(now);
				
				sqList.add(sqCmDataMonitor);
			}
			
			
			
			/*
			String sqlDataQueueName = "SQ_" + nodeInfo.getNodeCode() + "_TO_" + to.getNodeCode() +"_SQL_DATA";
			Queue sqSqlData = queueDao.getByQueueName(sqlDataQueueName);
			if(sqSqlData == null){
				sqSqlData = new Queue();
				String sqlDataQueueDesc = "从 [" + nodeInfo.getNodeName() + "] 发送到 [" + to.getNodeName() +"] 的SQL数据队列";
				sqSqlData.setId(UUIDGenerator.getUUID());
				sqSqlData.setNodeId(nodeInfo.getId());
				sqSqlData.setQueueType(Queue.QueueType.SQ.value());
				sqSqlData.setQueueName(sqlDataQueueName);
				sqSqlData.setQueueDesc(sqlDataQueueDesc);
				sqSqlData.setDestIp(destIp);
				sqSqlData.setDestQueueName(TlqConfig.LQ_SQL_DATA);
				sqSqlData.setBrokerType(Queue.BrokerType.TLQ.value());
				sqSqlData.setRemark("系统自动创建的发送队列");
				sqSqlData.setMtime(now);
				
				sqList.add(sqSqlData);
			}
			
			
			String sqlDataMonitorQueueName = "SQ_" + nodeInfo.getNodeCode() + "_TO_" + to.getNodeCode() +"_SQL_DATA_LOG";
			Queue sqSqlDataMonitor = queueDao.getByQueueName(sqlDataMonitorQueueName);
			if (sqSqlDataMonitor == null) {
				sqSqlDataMonitor = new Queue();

				String sqlDataMonitorQueueDesc = "从 [" + nodeInfo.getNodeName() + "] 发送到 [" + to.getNodeName() + "] 的SQL数据监控队列";
				sqSqlDataMonitor.setId(UUIDGenerator.getUUID());
				sqSqlDataMonitor.setNodeId(nodeInfo.getId());
				sqSqlDataMonitor.setQueueType(Queue.QueueType.SQ.value());
				sqSqlDataMonitor.setQueueName(sqlDataMonitorQueueName);
				sqSqlDataMonitor.setQueueDesc(sqlDataMonitorQueueDesc);
				sqSqlDataMonitor.setDestIp(destIp);
				sqSqlDataMonitor.setDestQueueName(TlqConfig.LQ_SQL_DATA_LOG);
				sqSqlDataMonitor.setBrokerType(Queue.BrokerType.TLQ.value());
				sqSqlDataMonitor.setRemark("系统自动创建的发送队列");
				sqSqlDataMonitor.setMtime(now);
				
				sqList.add(sqSqlDataMonitor);
			}*/
			
			
			String sqTestQueueName = "SQ_" + nodeInfo.getNodeCode() + "_TO_" + to.getNodeCode() +"_TEST";
			Queue sqTest = queueDao.getByQueueName(sqTestQueueName);
			if (sqTest == null) {
				sqTest = new Queue();

				String sqTestQueueNameDesc = "从 [" + nodeInfo.getNodeName() + "] 发送到 [" + to.getNodeName() + "] 的测试队列";
				sqTest.setId(UUIDGenerator.getUUID());
				sqTest.setNodeId(nodeInfo.getId());
				sqTest.setQueueType(Queue.QueueType.SQ.value());
				sqTest.setQueueName(sqTestQueueName);
				sqTest.setQueueDesc(sqTestQueueNameDesc);
				sqTest.setDestIp(destIp);
				sqTest.setDestQueueName(TlqConfig.LQ_TEST);
				sqTest.setBrokerType(Queue.BrokerType.TLQ.value());
				sqTest.setRemark("系统自动创建的发送队列");
				sqTest.setMtime(now);
				sqList.add(sqTest);
			}
			
			queueDao.betchInsertOrUpdateSenQueue(sqList);//先批量入库再说,如果TLQ添加队列失败，需要到页面逐个添加

			for (Queue queue : sqList) {
				status = tlqOptService.addSendQueue(queue);
			}
			
			msg = "初始化发送队列成功";
			logger.info(msg);
			status.setSuccess(true);
			status.setMsg(msg);
		} catch (Exception e) {
			msg = "初始化发送队列出现异常:" + e.fillInStackTrace();
			logger.error(msg);
			status.setSuccess(false);
			status.setMsg(msg);
		}
		return status;
	}

	public  List<Queue> getLocalQueueList() throws ServiceException{
		try {
			return queueDao.getLocalQueueList();
		} catch (DaoException e) {
			logger.error("本地队列获取失败！");
		}
		return null;
	}
}
